package com.xch.sboot.common.thread;

import cn.hutool.core.util.StrUtil;

import javax.validation.constraints.NotNull;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author xch
 * 2022/9/8 10:03
 */
public class NamedThreadFactory implements ThreadFactory {

    /**
     * 线程名称前缀
     */
    private final String prefix;

    /**
     * 线程组
     */
    private final ThreadGroup group;
    private final AtomicInteger threadNumber;
    private final boolean isDaemon;
    private final Thread.UncaughtExceptionHandler handler;

    public NamedThreadFactory(String prefix) {
        this(prefix, Boolean.FALSE);
    }

    public NamedThreadFactory(String prefix, boolean isDaemon) {
        this(prefix, null, isDaemon);
    }

    public NamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDaemon) {
        this(prefix, threadGroup, isDaemon, null);
    }

    public NamedThreadFactory(String prefix, ThreadGroup threadGroup, boolean isDaemon, Thread.UncaughtExceptionHandler handler) {
        this.threadNumber = new AtomicInteger(1);
        this.prefix = StrUtil.isBlank(prefix) ? "SBOOT" : prefix;
        if (null == threadGroup) {
            SecurityManager s = System.getSecurityManager();
            threadGroup = null != s ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
        }

        this.group = threadGroup;
        this.isDaemon = isDaemon;
        this.handler = handler;
    }

    @Override
    public Thread newThread(@NotNull Runnable r) {
        Thread thread = new Thread(this.group, r, prefix + threadNumber.getAndIncrement());
        if (this.isDaemon) {
            thread.setDaemon(Boolean.TRUE);
        } else {
            thread.setDaemon(Boolean.FALSE);
        }
        if (this.handler != null) {
            thread.setUncaughtExceptionHandler(handler);
        }
        return thread;
    }
}
